/**
 * 
 */
package za.co.sindi.oauth.core.service;

import net.oauth.transport.http.util.HttpConstants;
import za.co.sindi.oauth.core.context.HttpRequestContext;
import za.co.sindi.oauth.core.context.HttpResponseContext;
import za.co.sindi.oauth.core.context.RequestContext;
import za.co.sindi.oauth.core.context.ResponseContext;
import za.co.sindi.oauth.core.result.HttpResult;
import za.co.sindi.oauth.exception.ServiceException;
import za.co.sindi.oauth.server.config.RequestConfig;

/**
 * @author Buhake Sindi
 * @since 15 April 2012
 *
 */
public abstract class HttpService extends InvokeableService implements Service {

	/* (non-Javadoc)
	 * @see com.neurologic.oauth.core.service.Service#service(com.neurologic.oauth.server.config.RequestConfig, com.neurologic.oauth.core.context.RequestContext, com.neurologic.oauth.core.context.ResponseContext)
	 */
	@Override
	public HttpResult service(RequestConfig config, RequestContext requestContext, ResponseContext responseContext) throws ServiceException {
		// TODO Auto-generated method stub
		if (!(requestContext instanceof HttpRequestContext) || !(responseContext instanceof HttpResponseContext)) {
			throw new ServiceException("A HTTP request and response context is required.");
		}
		
		HttpResult result = null;
		try {
			HttpRequestContext request = (HttpRequestContext) requestContext;
			String requestMethod = request.getMethod();
			if (config != null && config.getMethod().equals(requestMethod)) {
				Object resultObject = super.service(config, requestContext, responseContext);
				if (resultObject != null) {
					if (!(resultObject instanceof HttpResult)) {
						throw new ServiceException("Expected result of type " + HttpResult.class.getName() + ", but found " + resultObject.getClass().getName()  + ".");
					}
					
					result = (HttpResult) resultObject;
				}
			} else {
				if (HttpConstants.METHOD_DELETE.equals(requestMethod)) {
					result = executeDelete(request);
				} else if (HttpConstants.METHOD_GET.equals(requestMethod)) {
					result = executeGet(request);
				} else if (HttpConstants.METHOD_HEAD.equals(requestMethod)) {
					result = executeHead(request);
				} else if (HttpConstants.METHOD_POST.equals(requestMethod)) {
					result = executePost(request);
				} else if (HttpConstants.METHOD_PUT.equals(requestMethod)) {
					result = executePut(request);
				} else if (HttpConstants.METHOD_TRACE.equals(requestMethod)) {
					result = executeTrace(request);
				} else {
					throw new ServiceException(requestMethod + " method is not a HTTP method.");
				}
			}
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			throw new ServiceException("service()", e);
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			throw new ServiceException("service()", e);
		}
			
		return result;
	}
	
	protected HttpResult executeDelete(HttpRequestContext requestContext) {
		return null;
	}
	
	protected HttpResult executeGet(HttpRequestContext requestContext) {
		return null;
	}
	
	protected HttpResult executeHead(HttpRequestContext requestContext) {
		return null;
	}
	
	protected HttpResult executePost(HttpRequestContext requestContext) {
		return null;
	}
	
	protected HttpResult executePut(HttpRequestContext requestContext) {
		return null;
	}
	
	protected HttpResult executeTrace(HttpRequestContext requestContext) {
		return null;
	}
}
